package com.fire.mongo.lessons;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.junit.Assert;
import org.junit.Test;

import org.springframework.boot.test.context.SpringBootTest;

/**
 * mongo的结构：
 * 客户端
 * 	- 数据库
 * 		- 集合
 * 			- 文档
 * 所以需要按一下步骤操作：
 * （1）创建mongo客户端：MongoClient
 * （2）选择客户端中的某个集合：MongoCollection
 * （3）选择集合中莫某个文档：Document
 * 接来下先看客户端的创建：MongoClientInstance()
 * @date 2022/4/19
 * @author zwd
 * @email zwd@hhh.com
 */
@SpringBootTest
public class MongoClientLearn {
	private String uri = "mongodb+srv://ZhouDongdong:123456zwd@nflix.4snkw.mongodb.net/test";
	private MongoClient mongoClient;
	private MongoDatabase database;

	private MongoCollection<Document> collation;
	private Document document;

	@Test
	public void MongoClientInstance() {
		/*
		 * 创建客户端，并传入相应的uri
		 */
		mongoClient = MongoClients.create(uri);

		Assert.assertNotNull(mongoClient);

		/*
		 * MongoClients可以创建客户端，但往往我们想要让创建出来的客户端具备一些额外的配置，比如
		 * 超时时间、等等。因此我们想要使用MongoClientSetting，该类包含有build方法，允许你配置不同的
		 * 客户端
		 */
		MongoClientSettings clientSettings = MongoClientSettings.builder()
				.applyConnectionString(new ConnectionString(uri))
				.applicationName("mflix")
				.applyToConnectionPoolSettings(
						builder -> builder.maxWaitTime(1000, TimeUnit.MILLISECONDS))
				.build();

		mongoClient = MongoClients.create(clientSettings);

		Assert.assertNotNull(mongoClient);
	}

	@Test
	public void MongoCollectionInstance() {
		/*
		MongoCollection 实例是用来读取 Document 数据和写入 Document 数据，
		在实际的业务场景中，我们主要用它来操作。

		想要创建一个 MongoCollection 实例，我们需要提供 MongoDatabase 实例中集合的名称。
		 */
		mongoClient = MongoClients.create(uri);
		database = mongoClient.getDatabase("sample_mflix");
		collation = database.getCollection("movies");

		/*
		现在我们使用MongoCollection来实现一个简单的查询操作,并返回一个游标
		例：我们查询 movies 集合中第10个之后的文档，并将文档的数量限制为20个
			在Mongo Shell中我们可以这样做
				[{$skip: 10}, {$limit: 20}]
		 */
		MongoIterable<Document> cursor = collation.find().skip(10).limit(20);

		/*
		所有的数据操作语言（DML）都可以通过MongoCollection实例来表达
		 */
		ArrayList<Document> documents = new ArrayList<>();
		Assert.assertEquals(20,cursor.into(documents).size());
	}

	@Test
	public void DocumentInstance(){
		mongoClient = MongoClients.create(uri);
		database = mongoClient.getDatabase("sample_mflix");
		collation = database.getCollection("movies");

		/*
		在Mongo中基础的数据结构是文档。我们可以认为文档是最好表达数据的一种方式。使用文档数据结构让你
		的数据定义和你的 OOP 对象更加贴近。

		现在我们来创建一个基本的文档数据模型,它像json格式
		例：
			{
				"name": {
					"first": "Zhou",
					"last": "Miaomiao"
				}
			}
		 */

		document = new Document("name",new Document("first","Zhou").append("last", "Miaomiao"));

		collation.insertOne(document);

		/*
		在Mongo中我们可以使用documents来做任何事
		- 定义数据模型
		- 定义查询
		- 定义更新操作
		- 定义配置设置
		....

		在java中既有 Document 类 和 Bson 类，Document 类实现 Bson 接口，因为 Documents 是
		Bson数据结构
		 */

		Assert.assertTrue(document instanceof Bson);
	}
}
